import { Injectable } from '@angular/core';
import { cloneDeep } from 'lodash-es';
import { Actions, MapItem, ControllerListItem } from './interface';
import { DomService } from './dom.service';
/**
 * 操作表单DOM的工具类
 */
@Injectable({
    providedIn: 'root'
})

export class EventEditorService {

    constructor(public domService: DomService) { }

    savedViewModel = [];

    /**
     * 去重
     * @param itemWithSameValue 
     * @param comparedPart 需要去重的是控制器还是命令
     * @returns 
     */
    public getUniqueContent(itemWithSameValue: any, comparedPart: string) {
        let value = cloneDeep(itemWithSameValue);
        for (let i = 0; i < value.length; i++) {
            for (let j = i + 1; j < value.length; j++) {
                if (comparedPart == 'controller') {
                    if (value[i]['controllerName']['id'] == value[j]['controllerName']['id']) {
                        value.splice(j, 1);
                        j--;
                    }
                }
                else if (comparedPart == 'command') {
                    if (value[i]['label'] == value[j]['label']) {
                        value.splice(j, 1);
                        j--;
                    }
                }
            }
        }
        itemWithSameValue = cloneDeep(value);
        return itemWithSameValue;
    }


    /**
     * 根据cmpId获取控制器名称
     * @param controller 
     * @returns 
     */
    public getControllerName(controller: any) {
        const savedViewModelItem = {
            controllerName: {
                label: '',
                name: '',
                id: '',
            },
            controllerList: []
        }
        savedViewModelItem.controllerName = cloneDeep(controller);
        this.savedViewModel.push(cloneDeep(savedViewModelItem));
        this.savedViewModel = this.getUniqueContent(this.savedViewModel, 'controller');
        return this.savedViewModel;
    }

    /**
     * 目标组件下所有可选的vm
     * @param domService 
     * @returns 
     */
    public allComponentList(domService: any) {
        const dom = domService.getDomJson();
        this.domService = domService;
        let componentListsItem = {
            componentId: '',
            viewModelId: ''
        }
        const allComponentList = [];
        for (let i = 0; i < dom.module.components.length; i++) {
            //筛选出root-component及form类型的component
            componentListsItem.componentId = cloneDeep(dom.module.components[i].id);
            componentListsItem.viewModelId = cloneDeep(dom.module.viewmodels[i].id);
            allComponentList.push(cloneDeep(componentListsItem));
        }
        return allComponentList;
    }

    /**
     * 处理actions节点的目标组件值
     * @param boundEventItem 绑定事件
     * @param vmid viewModelId
     * @returns 
     */
    public formTargetComponent(boundEventItem: any, vmid: string) {
        const allComponentList = this.allComponentList(this.domService);
        let targetComponent = {
            id: boundEventItem.controllerList.targetComponent,
            viewModelId: undefined,
        }
        if (allComponentList.length && boundEventItem.controllerList.targetComponent != undefined) {
            let viewModelId;
            allComponentList.forEach(component => {
                viewModelId = component.componentId == targetComponent.id ? component.viewModelId : viewModelId;
            });
            targetComponent.viewModelId = viewModelId;
        }
        else if (allComponentList.length) {
            //若不存在目标组件，则自动存放至当前viewmodel
            const componentList = allComponentList.find(componentListsItem => componentListsItem.viewModelId == vmid);
            targetComponent.id = componentList == undefined ? undefined : componentList.componentId;
            targetComponent.viewModelId = vmid;
        }
        return targetComponent;
    }

    /**
     * 获取actions节点和viewmodel节点的控制器，以便按照控制器分类所有命令
     * @param webCmdService 
     * @param domJson 
     * @returns 
     */
    public getController(webCmdService: any, domJson: any) {
        let savedViewModelFromActions = [];
        let savedViewModelFromVM;
        // 根据actions节点，获取控制器相关（savedViewModelFromActions）
        domJson.module.actions.forEach(actionItem => {
            actionItem.sourceComponent.map.forEach(mapItem => {
                savedViewModelFromActions = cloneDeep(this.getControllerName(mapItem.controller));
            })
        })
        // 根据viewModel节点，匹配cmpId获取控制器（savedViewModelFromVM）
        domJson.module.viewmodels.forEach(viewmodelItem => {
            viewmodelItem.commands.forEach(commandItem => {
                webCmdService.webCmds.forEach(webCmdItem => {
                    if (commandItem.cmpId == webCmdItem.Id) {
                        const controller = {
                            label: webCmdItem.Code,
                            name: webCmdItem.Name,
                            id: webCmdItem.Id,
                        }
                        savedViewModelFromVM = cloneDeep(this.getControllerName(controller));
                    }
                });
            })
        })

        // 合并savedViewModelFromActions及savedViewModelFromVM => savedViewModel
        const savedViewModel = savedViewModelFromActions ? this.getUniqueContent(savedViewModelFromActions.concat(savedViewModelFromVM), 'controller') : this.getUniqueContent(savedViewModelFromVM, 'controller');
        return savedViewModel;
    }

    /**
     * 1. 获取已绑定命令的参数值（来自actions节点）
     * 2. 获取暂未绑定的命令参数值（来自viewmodel节点）
     * @param savedViewModelItem 
     * @param controllerListItem 
     * @param domJson 
     */
    public getCommandParameter(savedViewModelItem: any, controllerListItem: ControllerListItem, domJson: any) {
        const actions = domJson.module.actions;
        actions.forEach(actionItem => {
            actionItem.sourceComponent.map.forEach(mapItem => {
                if (savedViewModelItem.controllerName.id == mapItem.controller.id) {
                    controllerListItem.label = mapItem.command.label;
                    controllerListItem.name = mapItem.command.name;
                    controllerListItem.id = mapItem.command.id;
                    controllerListItem.handlerName = mapItem.command.handlerName;
                    controllerListItem.property = cloneDeep(mapItem.command.params);
                    controllerListItem.cmpId = mapItem.controller.id;
                    controllerListItem.isNewGenerated = mapItem.controller.isNewGenerated || false;
                    controllerListItem.isInvalid = mapItem.command.isInvalid || false;
                    controllerListItem['isRTCmd'] = mapItem.command['isRTCmd'];
                    controllerListItem.targetComponent = mapItem.targetComponent['id'] ? mapItem.targetComponent['id'] : undefined;
                    savedViewModelItem.controllerList.push(cloneDeep(controllerListItem));
                }
            })
        })

        const viewmodels = domJson.module.viewmodels;
        viewmodels.forEach(viewmodelItem => {
            viewmodelItem.commands.forEach(commandsItem => {
                if (savedViewModelItem.controllerName.id == commandsItem.cmpId) {
                    controllerListItem.label = commandsItem.code;
                    controllerListItem.name = commandsItem.name;
                    controllerListItem.id = commandsItem.id;
                    controllerListItem.handlerName = commandsItem.handlerName;
                    controllerListItem.property = cloneDeep(commandsItem.params);
                    controllerListItem.cmpId = commandsItem.id;
                    controllerListItem.isNewGenerated = commandsItem.isNewGenerated || false;
                    controllerListItem['isRTCmd'] = commandsItem.command['isRTCmd'];
                    controllerListItem.isInvalid = commandsItem.isInvalid || false;
                    controllerListItem.targetComponent = commandsItem['targetComponent'] ? commandsItem['targetComponent'] : undefined;
                    savedViewModelItem.controllerList.push(cloneDeep(controllerListItem));
                }
            })
        })
        return savedViewModelItem;
    }

    /**
     * 获取已绑定命令的路径，并tag该命令
     * @param actionData action节点的数据
     * @param savedViewModelCopy viewModel节点的数据
     */
    public getPathAndTagBoundCommand(actionData: any, savedViewModelCopy: any) {
        actionData.forEach(actionItem => {
            const id = actionItem.sourceComponent.id;
            // 获取已绑定命令的路径
            let path = this.domService.controlBasicInfoMap.get(id) != undefined ? this.domService.controlBasicInfoMap.get(id).parentPathName : undefined;
            actionItem['path'] = this.domService.controlBasicInfoMap.get(id) != undefined ? `${path} > ` : '';
            actionItem.sourceComponent.map.forEach(mapItem => {
                savedViewModelCopy.forEach(savedViewModelItem => {
                    savedViewModelItem.controllerList.forEach(commandItem => {
                        // tag已绑定的命令
                        if (commandItem.label == mapItem.command.label) {
                            commandItem['tag'] = 'notInternal';
                        }
                    });
                });
            });
        });
        return actionData;
    }

    /**
     * 获取暂未绑定的命令
     * @param propertyDataId 
     * @param viewModelId 
     * @param savedViewModelCopy 
     * @returns 
     */
    public handlePathOfUnboundCommand(propertyDataId: string, viewModelId: string, savedViewModelCopy: any) {
        let viewModelData: Actions = {
            sourceComponent: {
                id: propertyDataId,
                viewModelId: viewModelId,
                map: []
            },
            path: '暂未绑定 '
        };
        savedViewModelCopy.forEach(savedViewModelCopyItem => {
            const controllerName = savedViewModelCopyItem.controllerName;
            savedViewModelCopyItem.controllerList.forEach(commandItem => {
                if (!commandItem['tag']) {
                    let mapItem: MapItem = {
                        event: {
                            label: undefined,
                            name: undefined,
                        },
                        targetComponent: cloneDeep(this.formTargetComponent(savedViewModelCopyItem, commandItem.targetComponent)),
                        command: {
                            id: commandItem.id,
                            label: commandItem.label,
                            name: commandItem.name,
                            handlerName: commandItem.handlerName,
                            params: cloneDeep(commandItem.property),
                            isNewGenerated: commandItem.isNewGenerated || false,
                            isRTCmd: commandItem['isRTCmd'],
                            isInvalid: commandItem.isInvalid || false,
                        },
                        controller: {
                            id: controllerName.id,
                            label: controllerName.label,
                            name: controllerName.name,
                        }
                    }
                    viewModelData.sourceComponent.map.push(cloneDeep(mapItem));
                }
            });
        });
        return viewModelData;
    }

    /**
     * 剔除非组件内的其他命令:root显示全部，其他子组件选自身的vm
     * 
     * @param viewModelId 
     * @param actionWithPath actions节点及对应的路径
     * @param action 
     * @returns 
     */
    public selectedCommandRules(viewModelId: string, actionWithPath: any, action: any) {
        if (viewModelId != "root-viewmodel") {
            actionWithPath.forEach(actionWithPathItem => {
                let mapArray = [];
                let mapExist = false;
                actionWithPathItem.sourceComponent.map.forEach(mapItem => {
                    if (mapItem.targetComponent.viewModelId == viewModelId) {
                        mapArray.push(cloneDeep(mapItem));
                        mapExist = true;
                    }
                })
                if (mapExist) {
                    const actionsItem = {
                        path: actionWithPathItem.path,
                        sourceComponent: {
                            id: actionWithPathItem.sourceComponent.id,
                            map: cloneDeep(mapArray),
                            viewModelId: actionWithPathItem.sourceComponent.viewModelId,
                        }
                    }
                    action.push(cloneDeep(actionsItem));
                }
            })
        }
        else {
            action = cloneDeep(actionWithPath);
        }
        return action;
    }

    /**
     * 事件编辑器-已有方法-命令路径处理 
     * @param propertyDataId 组件id
     * @param viewModelId 视图模型id
     * @param webCmdService 
     * @returns 
     */
    public getEventPath(propertyDataId: string, viewModelId: string, webCmdService: any) {
        const domJson = this.domService.getDomJson();
        const actionData = cloneDeep(domJson.module.actions);

        let controllerListItem: ControllerListItem = {
            label: '',
            name: '',
            id: '',
            handlerName: '',
            showTargetComponent: false,
            cmpId: '',
            componentLists: [],
            targetComponent: undefined,
            isNewGenerated: undefined,
            isRTCmd: undefined,
            isInvalid: false,
            property: []
        }

        // 1. 获取已绑定命令的参数值（来自actions节点）
        // 2. 获取暂未绑定的命令参数值（来自viewmodel节点）
        let savedViewModel = this.getController(webCmdService, domJson);
        savedViewModel.forEach(savedViewModelItem => {
            const actions = domJson.module.actions;
            actions.forEach(actionItem => {
                actionItem.sourceComponent.map.forEach(mapItem => {
                    if (savedViewModelItem.controllerName.id == mapItem.controller.id) {
                        controllerListItem.label = mapItem.command.label;
                        controllerListItem.name = mapItem.command.name;
                        controllerListItem.id = mapItem.command.id;
                        controllerListItem.handlerName = mapItem.command.handlerName;
                        controllerListItem.property = cloneDeep(mapItem.command.params);
                        controllerListItem.cmpId = mapItem.controller.id;
                        controllerListItem.isNewGenerated = mapItem.controller.isNewGenerated || false;
                        controllerListItem.isRTCmd = mapItem.command['isRTCmd'];
                        controllerListItem.isInvalid = mapItem.command.isInvalid || false;
                        controllerListItem.targetComponent = mapItem.targetComponent['id'] ? mapItem.targetComponent['id'] : undefined;
                        savedViewModelItem.controllerList.push(cloneDeep(controllerListItem));
                    }
                })
            })

            const viewmodels = domJson.module.viewmodels;
            viewmodels.forEach(viewmodelItem => {
                viewmodelItem.commands.forEach(commandsItem => {
                    const targetComponent = viewmodelItem.code;
                    if (savedViewModelItem.controllerName.id == commandsItem.cmpId) {
                        controllerListItem.label = commandsItem.code;
                        controllerListItem.name = commandsItem.name;
                        controllerListItem.id = commandsItem.id;
                        controllerListItem.handlerName = commandsItem.handlerName;
                        controllerListItem.property = cloneDeep(commandsItem.params);
                        controllerListItem.cmpId = commandsItem.id;
                        controllerListItem.isNewGenerated = commandsItem.isNewGenerated || false;
                        controllerListItem.isRTCmd = commandsItem.isRTCmd ;
                        controllerListItem.isInvalid = commandsItem.isInvalid || false;
                        controllerListItem.targetComponent = commandsItem['targetComponent'] || targetComponent ? commandsItem['targetComponent'] || targetComponent : undefined;
                        savedViewModelItem.controllerList.push(cloneDeep(controllerListItem));
                    }
                })
            })
            savedViewModelItem.controllerList = cloneDeep(this.getUniqueContent(savedViewModelItem.controllerList, 'command'));
        })

        const savedViewModelCopy = cloneDeep(savedViewModel);
        const actionsData = cloneDeep(this.getPathAndTagBoundCommand(actionData, savedViewModelCopy));
        const viewModelsData = cloneDeep(this.handlePathOfUnboundCommand(propertyDataId, viewModelId, savedViewModelCopy));
        const actionWithPath = actionsData.concat(viewModelsData);

        let action = [];
        action = cloneDeep(this.selectedCommandRules(viewModelId, actionWithPath, action));

        return {
            actionWithPath: action,
            viewModelDisplay: savedViewModel
        }
    }

}